package com.cipe.cmrs.dao;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.cipe.cmrs.model.RestrictedUiElements;
import com.cipe.cmrs.model.RestrictedUiElementsRolePrivileges;
import com.cipe.cmrs.model.Role;
import com.cipe.cmrs.model.User;

@Repository
public class RestrictedUiElementDao {
	
	protected Logger logger = LoggerFactory.getLogger(getClass());
	
	private static final String NULL_ID_MESSAGE = "Id cannot be null.";
	
	
    @PersistenceContext
    private EntityManager em;

	/**
	 * Returns all entities . 
	 * Result will also be ordered in ascending on the basis of id field 
	 * @return
	 */
	public List<RestrictedUiElements> findAll(Class<RestrictedUiElements> persistanceClass) {
		if (persistanceClass == null) {
			throw new IllegalArgumentException("Persistent Class can not be null");
		}
		String entityName = persistanceClass.getName();
		
		String sql = "select b from " + entityName + " b order by b.id asc";
		return getResultList(sql);
	}
	
	/**
	 * Find the entity of RestrictedUiElements with a given id.
	 * @param id
	 * @return
	 */
	public RestrictedUiElements findById(Class<RestrictedUiElements> persistanceClass, Serializable id) {
		if (id == null) {
			throw new IllegalArgumentException(NULL_ID_MESSAGE);
		}
		return (RestrictedUiElements) em.find(persistanceClass, id);
	}
	
	/**
	 * Merge the state of the given entity into the current persistence context. <br>
	 * <br>
	 * Simply delegates to merge(RestrictedUiElements entity) method of EntityManager class.
	 * 
	 * @see #merge
	 * @param entity
	 * @return the updated entity instance
	 */
	public RestrictedUiElements update(RestrictedUiElements entity) {
		return em.merge(entity);
	}
	
	@SuppressWarnings("unchecked")
	public List<RestrictedUiElements> getRestrictedUiElementsByUserRoles(User user) {
		List<Integer> uiElementIds = getRestrictedUiElementIds(user);
		List<Integer> values = new ArrayList<Integer>();

		StringBuilder queryBuilder = new StringBuilder();
		queryBuilder.append("from RestrictedUiElements ");
        if (uiElementIds.size() > 0) {
        	queryBuilder.append(" WHERE id IN (");
            int i = 1;
            for (; i < uiElementIds.size(); i++) {
            	queryBuilder.append("?" + i + ",");
                values.add(uiElementIds.get(i - 1));
            }
            queryBuilder.append("?" + i + ")");
            values.add(uiElementIds.get(i - 1));
        }

        Query query = em.createQuery(queryBuilder.toString());
        if (!uiElementIds.isEmpty()) {
            for (int i = 0; i < uiElementIds.size(); i++) {
                query.setParameter(i + 1, uiElementIds.get(i));
            }
        }

        List<RestrictedUiElements> list = query.getResultList();
	
		return list;
	}
	
	@SuppressWarnings("unused")
	private List<Integer> getRestrictedUiElementIds(User user){
		List<Integer> values = new ArrayList<Integer>();
		StringBuilder queryBuilder = new StringBuilder();
		queryBuilder.append("from RestrictedUiElementsRolePrivileges");
        if (user.getRoles().size() > 0) {
        	queryBuilder.append(" WHERE roleId IN (");
            List<Role> roles = new ArrayList<Role>(user.getRoles());
            int i = 1;
            for (; i < roles.size(); i++) {
            	queryBuilder.append("?" + i + ",");
                values.add(roles.get(i - 1).getId());
            }
            queryBuilder.append("?" + i + ")");
            values.add(roles.get(i - 1).getId());
        }

        Query query = em.createQuery(queryBuilder.toString());
        if (!values.isEmpty()) {
            for (int i = 0; i < values.size(); i++) {
                query.setParameter(i + 1, values.get(i));
            }
        }
        List<RestrictedUiElementsRolePrivileges> list = query.getResultList();
        List<Integer> uiElementIds = new ArrayList<Integer>();
        if (list != null && list.size() > 0) {
            for (RestrictedUiElementsRolePrivileges el : list) {
            	uiElementIds.add(el.getUielementId());
            }
        }

        return uiElementIds;
	}	
    
    public Query createQuery(String sqlString) {
        return em.createQuery(sqlString);
    }
    
	/**
	 * Result list for a JPQL query.  
	 * @param query
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<RestrictedUiElements> getResultList(String query) {
		Session session = (Session)em.getDelegate();		
		return session.createQuery(query).setCacheable(true).list();		
	}
}
